#include "Project.hxx"
#include "Sequence.hxx"
#include "TrackedObject.hxx"

Project::Project()
{
    _nextSequenceId = 0;
    _nextObjectId = 0;
    _nextClassId = 0;

    _activeSequence = 0;
    _view = 0;

    _projectType = TYPE_RECTANGLE;

    _name = "Project";
}

Project::~Project()
{
    for (int i = 0; i < _classes.size(); i++)
    {
        Class* cls = _classes.at(i);
        delete cls;
        cls = 0;
    }

    _classes.clear();

    for (int i = 0; i < _sequences.size(); i++)
    {
        Sequence* seq = _sequences.at(i);
        delete seq;
        seq = 0;
    }

    _sequences.clear();

    _activeClass = nullptr;
    _activeSequence = nullptr;
}

void Project::addSequence(Sequence *sequence)
{
    _sequences.push_back(sequence);
    _activeSequence = sequence;

    if (_view) _activeSequence->setVideoView(_view);
}

void Project::addClass(Class* cls)
{
    _classes.push_back(cls);
    _activeClass = cls;
}

void Project::addClass(std::string clsName)
{
    Class* cls = new Class();

    cls->setId(_nextClassId++);
    cls->setName(clsName);

    addClass(cls);
}

void Project::removeActiveSequence()
{
    if (_sequences.size() > 1 && _activeSequence)
    {
        for (int i = 0; i < _sequences.size(); i++)
        {
            Sequence* seq = _sequences.at(i);
            if (seq == _activeSequence)
            {
                _sequences.erase(_sequences.begin() + i);
                delete seq;
                seq = 0;

                _activeSequence = _sequences.at(0);
                break;
            }
        }
    }
}

void Project::removeActiveClass()
{
    // remove objects belong to a specific class.
    for (int i = 0; i < _sequences.size(); i++)
    {
        Sequence* seq = _sequences.at(i);

        std::vector<TrackedObject*>* objects = seq->getTrackedObjects();

        for (int j = 0; j < objects->size(); j++)
        {
            TrackedObject* obj = objects->at(j);

            if (obj->getClassIndex() == _activeClass->getId())
            {
                delete obj;
                objects->erase(objects->begin() + j);
                j--;
            }
        }
    }

    // remove the active class.
    for (int i = 0; i < _classes.size(); i++)
    {
        Class* cls = _classes.at(i);
        if (cls == _activeClass)
        {
            delete cls;
            _classes.erase(_classes.begin() + i);
            _activeClass = _classes.at(0);
            break;
        }
    }
}

int Project::getNegativeSampleClassId()
{
    int nid = -1;

    for (int i = 0; i < _classes.size(); i++)
    {
        Class* cls = _classes.at(i);

        if (strcmp("NegativeSample", cls->getName().c_str()) == 0)
        {
            nid = cls->getId();
            break;
        }
    }

    // Do not found negative sample class
    if (nid == -1)
    {
        Class* cls = new Class();
        cls->setId(getNextClassId());
        cls->setName("NegativeSample");

        addClass(cls);

        nid = cls->getId();
    }

    return nid;
}

void Project::setProjectType(std::string typeName)
{
    std::transform(typeName.begin(), typeName.end(), typeName.begin(), ::toupper);
    if (strcmp(typeName.c_str(), "FISHTRACKING") == 0)
    {
        _projectType = TYPE_FISH;
    }
    else if (strcmp(typeName.c_str(), "VIDEOSEGMENTATION") == 0)
    {
        _projectType = TYPE_POLYGON;
    }
    else
    {
        _projectType = TYPE_RECTANGLE;
    }
}

std::string Project::getProjectTypeName()
{
    std::string typeName;

    switch (_projectType)
    {
    case TYPE_RECTANGLE:
        typeName = "ObjectDetection";
        break;
    case TYPE_POLYGON:
        typeName = "VideoSegmentation";
        break;
    case TYPE_FISH:
        typeName = "FishTracking";
        break;

    default:
        typeName = "ObjectDetection";
        break;
    }

    return typeName;
}
